<template>
  <div class="user-import">
    <!-- 使用方法 -->
    <mu-sub-header>用户批量导入</mu-sub-header>
    <p>使用方法：按如下格式准备一张Exel表格（要求xlsx格式，即Office2007以上版本）， <strong style="color: red;">并保证数据在第一个Sheet中</strong> ，然后拖动文件到下方的上传栏（或点击选择也可）。权限对照表见下方。</p>
    <img src="@/assets/user_excel_example.png" alt="" class="user-excel-example">
    <!-- 权限对照表 -->
    <mu-sub-header>权限对照表</mu-sub-header>
    <mu-data-table
      stripe
      :columns="permColumns"
      :data="roles"
      no-data-text="暂无数据"
      :min-col-width="40"
    >
      <template #default="{ row }">
        <td class="is-center">{{ row.id }}</td>
        <td class="is-center">{{ row.text }}</td>
        <td class="is-center">{{ row.role_name }}</td>
        <td v-for="item in permissions" :key="item.id" class="is-center">
          <span v-if="roleHasPerm(row, item)">&radic;</span>
          <span v-else></span>
        </td>
      </template>
    </mu-data-table>
    <!-- 导入区 -->
    <div class="excel-input">
      <file-input @choose="chooseFile">
        <p style="text-align: center">请将Excel文件拖动到这里，或点击这里选择Excel文件。</p>
      </file-input>
    </div>
    <!-- 导入区预览 -->
    <mu-sub-header>导入预览</mu-sub-header>
    <mu-data-table
      stripe
      :columns="userColumns"
      :data="userList"
      no-data-text="暂无数据"
      :min-col-width="40"
      :loading="importing"
    >
      <template #default="{ row }">
        <td class="is-center">{{ row.username }}</td>
        <td class="is-center">{{ row.realname }}</td>
        <td class="is-center">{{ row.password }}</td>
        <td class="is-center">{{ roleToText(row.role) }}</td>
        <td class="is-center">{{ boolToText(row.is_active) }}</td>
        <td class="is-center">{{ row.status }}</td>
      </template>
    </mu-data-table>
    <!-- 确定按钮 -->
    <mu-button v-load="importing" color="success" class="import-button" @click="confirmImport">确定导入</mu-button>
  </div>
</template>

<script>
import api from '@/api'
import { encryptPassword } from '@/api/password-client'
import { mapGetters } from 'vuex'
import { readFile, getTable } from '@/util/excel'
import FileInput from '@/components/FileInput'

export default {
  name: 'UserImport',
  components: {
    FileInput
  },
  data() {
    return {
      importing: false,
      userList: []
    }
  },
  computed: {
    ...mapGetters({
      publickey: 'publickey',
      roles: 'roles',
      permissions: 'permissions',
      isPhone: 'isPhone'
    }),
    permColumns() {
      const marphWidth = this.isPhone ? 250 : undefined
      const cols1 = [
        { title: '权限编号', name: 'id', width: 60, align: 'center', class: 'paddingless' },
        { title: '权限名称', name: 'text', width: marphWidth, align: 'center', class: 'paddingless' },
        { title: '标识符', name: 'role_name', width: marphWidth, align: 'center', class: 'paddingless' }
      ]
      const cols2 = this.permissions.map(it => {
        return {
          title: it.text,
          name: it.code,
          width: 60,
          align: 'center',
          class: 'paddingless'
        }
      })
      return [...cols1, ...cols2]
    },
    userColumns() {
      const marphWidth = this.isPhone ? 160 : undefined
      return [
        { title: '用户名', name: 'username', width: marphWidth, align: 'center', class: 'paddingless' },
        { title: '真实姓名', name: 'realname', width: marphWidth, align: 'center', class: 'paddingless' },
        { title: '密码', name: 'password', width: marphWidth, align: 'center', class: 'paddingless' },
        { title: '用户权限', name: 'role', width: 130, align: 'center', class: 'paddingless' },
        { title: '是否可用', name: 'is_active', width: 60, align: 'center', class: 'paddingless' },
        { title: '状态', name: 'status', width: 100, align: 'center', class: 'paddingless' }
      ]
    }
  },
  methods: {
    roleHasPerm({ permissions }, { id }) {
      return permissions.indexOf(id) >= 0
    },
    // 权限编号转成文本
    roleToText(id) {
      if (id === 0) return '无隶属'
      const role = this.roles.find(it => it.id === id)
      return role ? role.text : '未知权限'
    },
    // 布尔值转文本
    boolToText(bool) {
      return bool ? '是' : '否'
    },
    // 选择文件时
    async chooseFile(file) {
      const fileData = await readFile(file)
      const jsonData = getTable(fileData, 0)
      const data = this.cleanData(jsonData)
      this.userList = data.map(it => ({
        ...it,
        status: '等待'
      }))
    },
    // 清洗整理数据
    cleanData(input) {
      const output = []
      const data = input.slice(1) // 移除首行
      for (const line of data) {
        if (line.length >= 5) {
          const [username, realname, password, role, is_active] = line
          if (!this.roles.find(it => it.id === parseInt(role))) {
            continue
          }
          output.push({
            username: username.toString(),
            realname: realname.toString(),
            password: password.toString(),
            role: parseInt(role),
            is_active: parseInt(is_active) === 1
          })
        } else {
          console.warn('自动忽略行：', line)
        }
      }
      return output
    },
    // 确定导入
    async confirmImport() {
      if (this.importing) {
        return
      }
      this.importing = true
      for (const item of this.userList) {
        item.status = '上传中'
        try {
          const payload = encryptPassword(this.publickey, item.password)
          payload.role = item.role
          payload.is_active = item.is_active
          await api.createUser(item.username, item.realname, payload)
          item.status = '成功'
        } catch (err) {
          item.status = '失败：' + err.message
        }
      }
      this.importing = false
    }
  }
}
</script>

<style>
.user-import .paddingless {
  padding: 2px;
}
.user-import th.paddingless {
  word-break: break-all;
  white-space: normal;
}
</style>

<style scoped>
.user-excel-example {
  display: block;
  width: 100%;
}
.excel-input {
  display: flex;
  justify-content: center;
}
.import-preview-box {
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
}
.import-button {
  display: block;
  margin: 0 auto;
  width: 300px;
}
.is-phone .import-button {
  width: 100%;
}
</style>
